package com.cnap.multiclouldmgmt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * 利用@EnableAsync注解开启异步任务支持
 *
 * * corePoolSize 当线程池被创建后，线
 * 程池中就会有指定数量的线程被创建用来等待任务的执行，
 * 这些线程被称为核心线程。即使它们是空闲的，
 * 它们也不会被销毁。除非设置了allowCoreThreadTimeOut参数。
 *  *
 *  * maximumPoolSize 线程池所能容纳的最大线程数量。
 *  *
 *  * keepAliveTime 用来指定非核心线程被创建后最多可以存活的时间。
 *  *
 *  * unit 用来设置上述时间的单位。
 *  *
 *  * workQueue 用来保存等待执行的任务。
 *  *
 *  * threadFactory（非必填参数，若不填写则使用默认值） 执行程序创建新线程时使用的工厂
 *  *
 *  * handler（非必填参数，若不填写则使用默认值） 拒绝策略
 *  *线程池的5种状态具体如下：
 *  *
 *  * （1）RUNNING：线程池创建之后的初始状态，这种状态下可以执行任务。
 *  *
 *  * （2）SHUTDOWN：该状态下线程池不再接受新任务，但是会将工作队列中的任务执行完毕。
 *  *
 *  * （3）STOP：该状态下线程池不再接受新任务，也不会处理工作队列中的剩余任务，并且将会中断所有工作线程。
 *  *
 *  * （4）TIDYING：该状态下所有任务都已终止或者处理完成，将会执行terminated()钩子方法。
 *  *
 *  * （5）TERMINATED：执行完terminated()钩子方法之后的状态。terminated钩子方法在Executor终止时调用，默认实现不执行任何操作
 *  *
 *  * 线程池的状态转换规则为：
 *  *
 *  * （1）线程池创建之后状态为RUNNING。
 *  *
 *  * （2）执行线程池的shutdown()实例方法，会使线程池状态从RUNNING转变为SHUTDOWN。
 *  *
 *  * （3）执行线程池的shutdownNow()实例方法，会使线程池状态从RUNNING转变为STOP。
 *  *
 *  * （4）当线程池处于SHUTDOWN状态时，执行其shutdownNow()方法会将其状态转变为STOP。
 *  *
 *  * （5）等待线程池的所有工作线程停止，工作队列清空之后，线程池状态会从STOP转变为TIDYING。
 *  *
 *  * （6）执行完terminated()钩子方法之后，线程池状态从TIDYING转变为TERMINATED。
 *  * AbortPolicy: 默认策略，抛出异常RejectedExecutionException，拒绝执行 。
 *  *
 *  * CallerRunsPolicy: 调用执行自己的线程运行任务，也就是直接在调用execute方法的线程中运行(run)被拒绝的任务，如果执行程序已关闭，则会丢弃该任务。因此这种策略会降低对于新任务提交速度，影响程序的整体性能。如果您的应用程序可以承受此延迟并且要求任何一个任务请求都要被执行的话，你可以选择这个策略。
 *  *
 *  * DiscardPolicy: 不处理新任务，直接丢弃掉。
 *  * DiscardOldestPolicy: 此策略将丢弃最早的未处理的任务请求。
 */
@Configuration
@EnableAsync
public class TaskConfig {
    // 声明一个线程池(并指定线程池的名字)
    @Bean("scaleTaskExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数5：线程池创建时候初始化的线程数
        executor.setCorePoolSize(50);
        //最大线程数5：线程池最大的线程数，只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(100);
        //缓冲队列500：用来缓冲执行任务的队列
        executor.setQueueCapacity(500);
        //允许线程的空闲时间60秒：当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);
        //线程池名的前缀：设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setThreadNamePrefix("DailyAsync-");
        executor.initialize();
        return executor;
    }


}
